#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
#include <assert.h>
#include <fcntl.h>
#include <sys/mman.h>          // Flags for open()
#include <sys/stat.h>           // Open() system call
#include <sys/types.h>          // Types for open()
#include <unistd.h>             // Close() system call
#include <string.h>             // Memory setting and copying
#include <getopt.h>             // Option parsing
#include <errno.h>              // Error codes
#include <string.h>
#include <poll.h>
#include "util.h"               // Miscellaneous utilities
#include "conversion.h"         // Convert bytes to MiBs
#include "libaxidma.h"          // Interface ot the AXI DMA library
#include <pthread.h>
#include "../pcm/pcm.h"

#define MAXLENGTH 1020
static unsigned char rbuffer[MAXLENGTH] = { 0 };
static unsigned char sbuffer[MAXLENGTH] = { 0 };

axidma_dev_t axidma_dev_pcm;
struct dma_transfer trans;
struct dma_transfer trans_2;
unsigned int cnt=0;
int main(int argc, char **argv) {
	char c[4] = {0}; //mycmd
	int i = 0, tmp_val = 0, rc=0;
	const array_t *tx_chans, *rx_chans;

	memset(&trans, 0, sizeof(trans));
	memset(&trans_2, 0, sizeof(trans));
	for (i = 0; i < MAXLENGTH; i++) {
		sbuffer[i] = i ;
	}
	for (i = 0; i < 990 ; i++) {
		sbuffer[26+i] = i+1 ;
	}

	sbuffer[0] = 0xaa;
	sbuffer[25] = 0xCC;
	tmp_val = (sbuffer[26] << 8) | sbuffer[27];
	for (i = 0; i < 990 - 2; i++) {
		tmp_val ^= ((sbuffer[28 + i] << 8) | sbuffer[29 + i]);
		i++;
	}
	sbuffer[MAXLENGTH - 4] = tmp_val >> 8;
	sbuffer[MAXLENGTH - 3] = tmp_val & 0xff;
	printf("sbuffer[MAXLENGTH-4]=%#x\n", sbuffer[MAXLENGTH - 4]);
	printf("sbuffer[MAXLENGTH-3]=%#x\n", sbuffer[MAXLENGTH - 3]);

	axidma_cnt_init();
	axidma_dev_pcm = axidma_init();
	if (axidma_dev_pcm == NULL)
	{
		fprintf(stderr, "Error: Failed to initialize the AXI DMA device.\n");
		rc = 1;
		goto close_output;
	}

	tx_chans = axidma_get_dma_tx(axidma_dev_pcm);
	if (tx_chans->len < 1) {
		fprintf(stderr, "Error: No transmit channels were found.\n");
		rc = -ENODEV;
		goto destroy_axidma;
	}

	rx_chans = axidma_get_dma_rx(axidma_dev_pcm);
	if (rx_chans->len < 1) {
		fprintf(stderr, "Error: No receive channels were found.\n");
		rc = -ENODEV;
		goto destroy_axidma;
	}

	/* 如果用户没有指定通道，我们假设发送和接收通道是编号最低的通道。 */
	// if (trans.input_channel == -1 && trans.output_channel == -1)
	{
		trans.input_channel = tx_chans->data[1];
		trans.output_channel = rx_chans->data[1];
	}
	trans.output_size = MAXLENGTH;
	trans.input_size = MAXLENGTH;
	trans.output_buf = axidma_malloc(axidma_dev_pcm, trans.output_size);
	if (trans.output_buf == NULL) {
		rc = -ENOMEM;
		axidma_free(axidma_dev_pcm, trans.output_buf, trans.output_size);
	}
	memset(trans.output_buf, 0, trans.output_size);
	trans.input_buf = axidma_malloc(axidma_dev_pcm, trans.input_size);
	if (trans.input_buf == NULL) {
		fprintf(stderr, "Failed to allocate the input buffer.\n");
		rc = -ENOMEM;
		axidma_free(axidma_dev_pcm, trans.input_buf, trans.input_size);
	}
	memset(trans.input_buf, 0, trans.input_size);
//#############################################
	/* 如果用户没有指定通道，我们假设发送和接收通道是编号最低的通道。 */
	// if (trans.input_channel == -1 && trans.output_channel == -1)
	{
		trans_2.input_channel = tx_chans->data[2];
		trans_2.output_channel = rx_chans->data[2];
	}
	trans_2.output_size = MAXLENGTH;
	trans_2.input_size = MAXLENGTH;
	trans_2.output_buf = axidma_malloc(axidma_dev_pcm, trans_2.output_size);
	if (trans_2.output_buf == NULL) {
		rc = -ENOMEM;
		axidma_free(axidma_dev_pcm, trans_2.output_buf, trans_2.output_size);
	}
	memset(trans_2.output_buf, 0, trans_2.output_size);
	trans_2.input_buf = axidma_malloc(axidma_dev_pcm, trans_2.input_size);
	if (trans_2.input_buf == NULL) {
		fprintf(stderr, "Failed to allocate the input buffer.\n");
		rc = -ENOMEM;
		axidma_free(axidma_dev_pcm, trans_2.input_buf, trans_2.input_size);
	}
	memset(trans_2.input_buf, 0, trans_2.input_size);

	pcm_reset();
	unsigned int axiadm_1_cnt = get_axidma_cnt(1);
	unsigned int axiadm_2_cnt = get_axidma_cnt(2);
	printf("axiadm_1_cnt = %d \n", axiadm_1_cnt);
	printf("axiadm_2_cnt = %d \n", axiadm_2_cnt);

	while (1) {
		bzero(c, sizeof(c));
		fgets(c, sizeof(c), stdin);

		if(c[0] == '1')
		{
			while(1)
			{
				cnt = get_axidma_cnt(1);
				if(cnt > axiadm_1_cnt)
				{
					axiadm_1_cnt++ ;
					pulse_flag(1);
					rc = axidma0read(axidma_dev_pcm, &trans, rbuffer);
					if(rc < 0) {
						printf("no read data ....\n");
					}
					else
					{
						printf("%02x %02x %02x %02x  %02x %02x %02x %02x  %02x %02x ; %02x %02x %02x %02x\n",
							rbuffer[0],rbuffer[1],rbuffer[2],rbuffer[3], rbuffer[4], rbuffer[5],rbuffer[6], rbuffer[7],
							rbuffer[8],rbuffer[9],rbuffer[1020-4],rbuffer[1020-3],rbuffer[1020-2],rbuffer[1020-1]);
					}
					memset(rbuffer, 0, PCM_BAG_SIZE);
				}
				usleep(1);
			}
		}
		else if(c[0] == '2')
		{
			while(1)
			{
				cnt = get_axidma_cnt(2);
				if(cnt > axiadm_2_cnt)
				{
					axiadm_2_cnt++ ;

					pulse_flag(2);
					rc = axidma0read(axidma_dev_pcm, &trans_2, rbuffer);
					if(rc < 0) {
						printf("no read data ....\n");
					}
					else
					{
						printf("%02x %02x %02x %02x  %02x %02x %02x %02x  %02x %02x ; %02x %02x %02x %02x\n",
							rbuffer[0],rbuffer[1],rbuffer[2],rbuffer[3], rbuffer[4], rbuffer[5],rbuffer[6], rbuffer[7],
							rbuffer[8],rbuffer[9],rbuffer[1020-4],rbuffer[1020-3],rbuffer[1020-2],rbuffer[1020-1]);
					}
					memset(rbuffer, 0, PCM_BAG_SIZE);
				}
				usleep(1);
			}
		}
		//**********************************************************
//		if (c[0] == 's') //422_1
//			{
//					printf("send----------------------------------------------------------\n");
//					printf("sbuffer[1]=%x, sbuffer[1020-4]=%x\n", sbuffer[1], sbuffer[MAXLENGTH-4]);
//
//	//				PCMSend(0, sbuffer, MAXLENGTH);
//
//					for(int i=0; i<10; i++)
//					{
//						rc = axidma0send(axidma_dev_pcm, &trans, sbuffer);
//						if(rc < 0)
//						{
//							printf("send error\n");
//							goto ret;
//						}
//						sbuffer[1]++;
//						sbuffer[MAXLENGTH - 4]++;
//						printf("send ....\n");
//					}
//			}
//		else if(c[0] == '0') ////422_2
//		{
//			printf("send----------------------------------------------------------\n");
//			printf("sbuffer[1]=%x, sbuffer[1020-4]=%x\n", sbuffer[1], sbuffer[MAXLENGTH-4]);
//
//			rc = axidma0send(axidma_dev_pcm, &trans_2, sbuffer);
//			if(rc < 0)
//			{
//				printf("send error\n");
//				goto ret;
//			}
//
//			sbuffer[1]++;
//			sbuffer[MAXLENGTH - 4]++;
//		}
//		else if(c[0] == 'g')
//		{
//			cnt = get_axidma_cnt(2);
//			if(cnt > axiadm_2_cnt)
//			{
//				axiadm_2_cnt++ ;
//				rc = axidma0read(axidma_dev_pcm, &trans_2, rbuffer);
//				if(rc < 0) {
//					printf("no read data ....\n");
//				}
//				else
//				{
//					printf("recv------------------------------------------------------------------\n");
//					printf("%x %x %x %x ; %x %x %x %x \n", rbuffer[0],rbuffer[1],rbuffer[2],rbuffer[3],
//							           rbuffer[1020-4],rbuffer[1020-3],rbuffer[1020-2],rbuffer[1020-1]);
//				}
//				memset(rbuffer, 0, PCM_BAG_SIZE);
//			}
//		}
//		else if(c[0] == '3')
//		{
//			//for(int ii=0;ii<1000;ii++)
//			{
//				printf("1 send-------------------------\n");
//				for(int i=0; i<16 ; i++)
//				{
//					printf("%02x ", sbuffer[26+i]);
//					if((i%16)==15) printf("\n");
//				}
//
//				rc = axidma0send(axidma_dev_pcm, &trans, sbuffer);
//				if(rc < 0)
//				{
//					printf("send error\n");
//					goto ret;
//				}
//				sbuffer[26]++;
//				tmp_val = (sbuffer[26] << 8) | sbuffer[27];
//				for (i = 0; i < 990 - 2; i++) {
//					tmp_val ^= ((sbuffer[28 + i] << 8) | sbuffer[29 + i]);
//					i++;
//				}
//				sbuffer[MAXLENGTH - 4] = tmp_val >> 8;
//				sbuffer[MAXLENGTH - 3] = tmp_val & 0xff;
//				sleep_ms(20);
//				rc = axidma0read(axidma_dev_pcm, &trans_2, rbuffer);
//				if(rc < 0) {
//					printf("no read data ....\n");
//				}
//				else
//				{
//					printf("2 recv-----------------------\n");
//					for(int i=0; i<16; i++)
//					{
//						printf("%02x ", rbuffer[i]);
//						if((i%16)==15) printf("\n");
//					}
//					printf("\n");
//				}
//				memset(rbuffer, 0, PCM_BAG_SIZE);
//			//	sleep(1);
//			}
//
//		}
//		else if(c[0] == '4')
//		{
//			rc = axidma0send(axidma_dev_pcm, &trans_2, sbuffer);
//			if(rc < 0)
//			{
//				printf("send error\n");
//				goto ret;
//			}
//			sbuffer[31]++;
//			sbuffer[30] = sbuffer[31];
//			tmp_val = (sbuffer[26] << 8) | sbuffer[27];
//			for (i = 0; i < 990 - 2; i++) {
//				tmp_val ^= ((sbuffer[28 + i] << 8) | sbuffer[29 + i]);
//				i++;
//			}
//			sbuffer[MAXLENGTH - 4] = tmp_val >> 8;
//			sbuffer[MAXLENGTH - 3] = tmp_val & 0xff;
//			printf("sbuffer[MAXLENGTH-4]=%#x\n", sbuffer[MAXLENGTH - 4]);
//			printf("sbuffer[MAXLENGTH-3]=%#x\n", sbuffer[MAXLENGTH - 3]);
//			sleep_ms(200);
//			rc = axidma0read(axidma_dev_pcm, &trans, rbuffer);
//			if(rc < 0) {
//				printf("no read data ....\n");
//			}
//			else
//			{
//				printf("-------------------------\n");
//				for(int i=0; i<PCM_BAG_SIZE; i++)
//				{
//					printf("%02x ", rbuffer[i]);
//					if((i%16)==15) printf("\n");
//				}
//				printf("\n");
//			}
//			memset(rbuffer, 0, PCM_BAG_SIZE);
//		}
//		else
//			printf("cmd error\n");
	}

	destroy_axidma: axidma_destroy(axidma_dev_pcm);
	close_output: assert(close(trans.output_fd) == 0);
// close_input:
//     assert(close(trans.input_fd) == 0);
	ret: return rc;
}
